﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using T19ShotBlock.BaseClass;

namespace T19ShotBlock
{    
    public partial class FrmBlock : Form
    {
        private Bitmap bmBackground;//背景图片资源
        private Bitmap bmPaddle;//挡板图片资源
        private static readonly Rectangle GamePaddleRect 
            = new Rectangle(39, 1, 93, 23);//挡板资源在合图中的矩形位置
        private Point centerOfPaddle;//挡板中心位置

        private Bitmap bmBlock;//砖块图片资源
        private static readonly Rectangle GameBlockRect
            = new Rectangle(139, 1, 62, 27);//砖块资源在合图中的矩形位置

        private Block[,] blocks = new Block[12, 14];//砖块显示地图

        private int gameLevel = 1;//游戏级别

        private Bitmap bmBall;//弹球图片资源
        private static readonly Rectangle GameBallRect = new Rectangle(1, 1, 36, 36);//弹球资源在合图中的矩形位置

        private Rectangle paddleRect;//挡板的位置

        [System.Runtime.InteropServices.DllImport("winmm")]
        public static extern bool PlaySound(string szSound, int hMode, int i);//音效播放扩展方法

        private int gameLives = 4;//玩家生命值:5

        private bool isGameOver = false;//游戏结束状态

        private bool bSounding = false;//音效播放控制

        public FrmBlock()
        {
            InitializeComponent();
        }

        private void FrmBlock_Load(object sender, EventArgs e)
        {
            this.LoadPictures();
            //设置挡板的初始位置
            centerOfPaddle.X = this.ClientRectangle.Width / 2;//屏幕中间(水平)
            centerOfPaddle.Y = this.ClientRectangle.Height - 30;//屏幕底部略上(垂直)

            this.RandomBlockMap();
            Ball.BallRect = new Rectangle(centerOfPaddle.X - 36 / 2, centerOfPaddle.Y - 32, 36, 36);
            Ball.BallDirection = new Vector2(1.0f, -1.0f);

            paddleRect = new Rectangle(
                this.ClientRectangle.Width / 2 - 48,
                this.ClientRectangle.Height -33,
                96,26);

            this.TimerRefreshScreen.Start();


        }

        //利用双缓冲机制绘制游戏界面
        protected override void OnPaint(PaintEventArgs e)
        {
            //1.在内存中建立绘制区域
            Bitmap bufferBm = new Bitmap(this.ClientRectangle.Width - 1,
                this.ClientRectangle.Height - 1);
            Graphics g = Graphics.FromImage(bufferBm);
            //2.在内存中绘制所有图片资源
            this.DrawGame(g);
            //3.把内存中的区域一次性绘制在屏幕上
            e.Graphics.DrawImage(bufferBm, 0, 0);
            //4.释放当前内存区域
            g.Dispose();
            base.OnPaint(e);
        }   

        /// <summary>
        /// 载入图片资源
        /// </summary>
        private void LoadPictures()
        {
            bmBackground = BitmapHelper.LoadBm("Background");
            Bitmap bmBreak = BitmapHelper.LoadBm("Break");
            //从"break.bmp"合图中的指定位置复制挡板图片资源
            bmPaddle = bmBreak.Clone(GamePaddleRect,bmBreak.PixelFormat);
            //从"break.bmp"合图中的指定位置复制砖块图片资源
            bmBlock = bmBreak.Clone(GameBlockRect, bmBreak.PixelFormat);
            //从"break.bmp"合图中的指定位置复制弹球图片资源
            bmBall = bmBreak.Clone(GameBallRect, bmBreak.PixelFormat);
        }

        /// <summary>
        /// 游戏界面绘制
        /// </summary>
        /// <param name="g"></param>
        private void DrawGame(Graphics g)
        {
            //绘制背景
            g.DrawImage(bmBackground, 
                new Rectangle(0, 0,
                this.ClientRectangle.Width - 1, 
                this.ClientRectangle.Height - 1));
            //绘制挡板 宽度：93 ，高度: 23
            g.DrawImage(bmPaddle,
                new Rectangle(centerOfPaddle.X - 93 / 2, centerOfPaddle.Y,93,23)
                );
            //绘制砖块 宽度：62，高度：27
            for (int row = 0; row < 12; row++)
            {
                for (int col = 0; col < 14; col++)
                {
                    if (blocks[row,col].IsBlock)
                    {
                        g.DrawImage(bmBlock, blocks[row, col].BlockRect);
                    }
                }
            }
            //绘制弹球 宽度：36，高度：36
            //绘制静态弹球
            //g.DrawImage(bmBall, 
            //    new Rectangle(centerOfPaddle.X - 36 / 2, centerOfPaddle.Y - 36, 36, 36));
            //绘制动态弹球
            g.DrawImage(bmBall,Ball.BallRect);
            //绘制游戏信息(文本方式)
            g.DrawString("关卡" + gameLevel.ToString(),
                new Font("仿宋", 24),
                new SolidBrush(Color.White),
                new Point(5, 5));
            g.DrawString("生命" + (gameLives+1).ToString(),
                new Font("仿宋", 24),
                new SolidBrush(Color.White),
                new Point(700, 5));
            if (isGameOver)
            {
                g.DrawString("游戏结束" + (gameLives + 1).ToString(),
                    new Font("仿宋", 48),
                    new SolidBrush(Color.White),
                    new Point(240, 280));
            }
        }


        /// <summary>
        /// 处理鼠标移动事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FrmBlock_MouseMove(object sender, MouseEventArgs e)
        {
            //移动挡板(水平移动) 改变Paddle的中心坐标,边界碰撞(游戏元素与游戏场景)处理
            if (e.X <= 93 / 2)//最左端
            {
                centerOfPaddle.X = 93 / 2;
            }
            else if (e.X >= this.ClientRectangle.Width - 93 / 2)//最右端
            {
                centerOfPaddle.X = this.ClientRectangle.Width - 93 / 2;
            }
            else
            {
                centerOfPaddle.X = e.X;
            }

            //更新挡板位置
            paddleRect.X = centerOfPaddle.X - 48;

            //this.Invalidate();
        }

        /// <summary>
        /// 产生随机砖块地图
        /// </summary>
        private void RandomBlockMap()
        {
            for (int row = 0; row < 12; row++)
                for (int col = 0; col < 14; col++)
                {
                    blocks[row, col] = new Block();
                    if (RandomHelper.GetRandomInt() < gameLevel)
                    {
                        blocks[row, col].IsBlock = true;
                        blocks[row, col].BlockRect
                            = new Rectangle(62*col, row*27+60, 62, 27);
                    }
                }
        }

        /// <summary>
        /// 处理计时器工作：刷新屏幕显示
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void timerRefreshScreen_Tick(object sender, EventArgs e)
        {
            Ball.BallRect.X += (int)(Ball.BallDirection.X * 8.0f);
            Ball.BallRect.Y += (int)(Ball.BallDirection.Y * 6.0f);
            //if (IsHit())
            //    Play("Hit");
            //if (IsKill())
            //    Play("Kill");

            if (IsHit() && !bSounding)
            {
                Play("Hit");
                bSounding = true;
                this.TimerAfterSound.Start();
            }
            if (IsKill() && !bSounding)
            {
                Play("Kill");
                bSounding = true;
                this.TimerAfterSound.Start();
            }

            if (IsLost())
                Play("Lost");
            if (IsVictory())
            {
                Play("Victory");
                this.TimerRefreshScreen.Stop();
                this.TimerWait.Start();
            }

            this.IsGameOver();
            if (isGameOver)
            {
                this.TimerRefreshScreen.Stop();
            }

            this.Invalidate();
        }

        /// <summary>
        /// 关卡等待时间控制
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TimerWait_Tick(object sender, EventArgs e)
        {
            this.TimerWait.Stop();
            gameLevel++;//进入下一关
            RandomBlockMap();//产生下一关的随机地图
            Ball.BallRect.X = this.ClientRectangle.Width / 2 - 18;
            Ball.BallRect.Y = this.ClientRectangle.Height - RandomHelper.GetRandomInt(35,60);
            Ball.BallDirection = new Vector2(1.0f, -1.0f);
            this.TimerRefreshScreen.Start();
        }

        /// <summary>
        /// 音效间隔播放控制
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TimerAfterSound_Tick(object sender, EventArgs e)
        {
            bSounding = false;
            this.TimerAfterSound.Stop();
        }

        /// <summary>
        /// 碰撞(边界)处理：改变弹球的方向
        /// </summary>
        private bool IsHit()
        {
            //与边框碰撞
            if (Ball.BallRect.X <= 3)//左边框
            {
                Ball.BallDirection.X = -Ball.BallDirection.X;
                return true;
            }
            if (Ball.BallRect.X>=this.ClientRectangle.Width -39)//右边框
            {
                Ball.BallDirection.X = -Ball.BallDirection.X;
                return true;
            }
            if (Ball.BallRect.Y <= 3)//上边框
            {
                Ball.BallDirection.Y = -Ball.BallDirection.Y;
                return true;
            }
            if (Ball.BallRect.IntersectsWith(paddleRect))//挡板
            {
                Ball.BallDirection.Y = -Ball.BallDirection.Y;
            }
            return false;
        }

        /// <summary>
        /// 与砖块发生碰撞
        /// </summary>
        /// <returns></returns>
        private bool IsKill()
        {
            for (int row = 0; row < 12; row++)
            {
                for (int col = 0; col < 14; col++)
                {
                    if (blocks[row, col].IsBlock
                        && blocks[row, col].BlockRect.IntersectsWith(Ball.BallRect))
                    {
                        if (Math.Abs(blocks[row, col].BlockRect.X - Ball.BallRect.X) < 6
                            || Math.Abs(blocks[row, col].BlockRect.X - Ball.BallRect.X + 93 - 36) < 6)//与砖块的左右侧面发生碰撞
                        {
                            Ball.BallDirection.X = -Ball.BallDirection.X;
                        }
                        else//与砖块的上下碰撞
                        {
                            Ball.BallDirection.Y = -Ball.BallDirection.Y;
                        }
                        //是砖块消失
                        blocks[row, col].IsBlock = false;
                        return true;
                    }
                }
            }
            return false;
        }

        /// <summary>
        /// 播放指定音效
        /// </summary>
        /// <param name="waveName"></param>
        private void Play(string waveName)
        {
            PlaySound(Application.StartupPath + "\\GameSounds\\" + waveName + ".wav", 0, 1);
        }

        /// <summary>
        /// 判断是否接住弹球
        /// </summary>
        /// <returns></returns>
        private bool IsLost()
        {
            if (Ball.BallRect.Y > this.ClientRectangle.Height - 18)
            {
                Ball.BallRect.Y = this.ClientRectangle.Height - RandomHelper.GetRandomInt(35, 60);
                Ball.BallDirection = new Vector2(1.0f, -1.0f);
                gameLives--;
                return true;
            }
            return false;
        }

        private bool IsVictory()
        {
            for (int row = 0; row < 12; row++)
            {
                for (int col = 0; col < 14; col++)
                {
                    if (blocks[row, col].IsBlock)
                    {
                        return false;
                    }
                }

            }
            return false;
        }

        /// <summary>
        /// 判断游戏是否结束
        /// </summary>
        private void IsGameOver()
        {
            if (gameLives < 0)
                isGameOver = true;
        }
    }
}
